package it.koutifaris.travianmap.ui.touch;

import it.koutifaris.travianmap.model.Village;
import it.koutifaris.travianmap.ui.PointToVillageHelper;
import it.koutifaris.travianmap.ui.animation.Animator;
import it.koutifaris.travianmap.ui.animation.FlingHelper;
import it.koutifaris.travianmap.ui.animation.NullAnimation;
import it.koutifaris.travianmap.ui.animation.Scheduler;
import it.koutifaris.travianmap.ui.viewstate.DynamicViewState;
import it.koutifaris.travianmap.ui.viewstate.ViewStateSource;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;

public class WolrdMapOnGestureListener extends SimpleOnGestureListener implements OnScaleGestureListener {

	private final ViewStateSource viewStateSource;
	private final Scheduler viewPoster;
	private final PointToVillageHelper pointToVillageHelper;
	private final OnVillageTouchHandler onVillageTapHandler;
	private Animator animation;

	public WolrdMapOnGestureListener(
			ViewStateSource viewStateSource,
			Scheduler viewPoster,
			OnVillageTouchHandler onVillageTapHandler,
			PointToVillageHelper pointToVillageHelper) {

		this.viewStateSource = viewStateSource;
		this.viewPoster = viewPoster;
		this.onVillageTapHandler = onVillageTapHandler;
		this.pointToVillageHelper = pointToVillageHelper;
		this.animation = new Animator(viewPoster, NullAnimation.nullAnimation());
	}

	@Override
	public boolean onDown(MotionEvent e) {
		animation.stop();

		return true;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
		translateToNewCoords(distanceX, distanceY);

		return true;
	}

	private void translateToNewCoords(float distanceX, float distanceY) {
		int newX = getViewState().getX() + (int) distanceX;
		int newY = getViewState().getY() + (int) distanceY;
		getViewState().updatePosition(newX, newY);
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
		float vx = -fromSecondsToMillis(velocityX);
		float vy = -fromSecondsToMillis(velocityY);
		// animation = new FlingHelper(viewStateSource, viewPoster, vx, vy);
		// animation.start();

		animation = new Animator(viewPoster, new FlingHelper(viewStateSource, vx, vy));
		animation.start();

		return true;
	}

	@Override
	public boolean onScale(ScaleGestureDetector detector) {
		float newZoom = getViewState().getZoom() * detector.getScaleFactor();
		getViewState().setZoom(newZoom, detector.getFocusX(), detector.getFocusY());

		return true;
	}

	@Override
	public boolean onScaleBegin(ScaleGestureDetector detector) {
		return true;
	}

	@Override
	public void onScaleEnd(ScaleGestureDetector detector) {
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		Village village = getVillageFromEvent(e);

		if (village != null) {
			onVillageTapHandler.onVillageTapped(village);
		}

		return true;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		Village village = getVillageFromEvent(e);

		if (village != null) {
			onVillageTapHandler.onVillageLongPress(village);
		}
	}

	private Village getVillageFromEvent(MotionEvent e) {
		return pointToVillageHelper.getVillageFromPoint((int) e.getX(), (int) e.getY());
	}

	private float fromSecondsToMillis(float velocity) {
		return velocity / 1000;
	}

	private DynamicViewState getViewState() {
		return viewStateSource.getViewState();
	}

}
